﻿using System.Text;
using WikiMaml.Macros;
using WikiMaml.Renderers;
using WikiPlex;
using WikiPlex.Compilation;
using WikiPlex.Compilation.Macros;
using WikiPlex.Formatting;
using WikiPlex.Parsing;
using IndentationRenderer = WikiPlex.Formatting.IndentationRenderer;
using LinkRenderer = WikiPlex.Formatting.LinkRenderer;
using ListItemRenderer = WikiPlex.Formatting.ListItemRenderer;
using SourceCodeRenderer = WikiPlex.Formatting.SourceCodeRenderer;
using TableRenderer = WikiPlex.Formatting.TableRenderer;
using TableScopeAugmenter = WikiMaml.Augmenters.TableScopeAugmenter;
using TextFormattingRenderer = WikiPlex.Formatting.TextFormattingRenderer;

namespace WikiMaml
{
    /// <summary>
    /// The public entry point for the maml engine.
    /// </summary>
    public class RenderingEngine : IRenderingEngine
    {
        private static readonly IMacroCompiler compiler = new MacroCompiler();

        static RenderingEngine()
        {
            // macros registration
            WikiPlex.Macros.Unregister<HeadingsMacro>();
            WikiPlex.Macros.Unregister<HorizontalLineMacro>();
            WikiPlex.Macros.Unregister<ImageMacro>();
            WikiPlex.Macros.Unregister<SyndicatedFeedMacro>();
            WikiPlex.Macros.Unregister<SilverlightMacro>();
            WikiPlex.Macros.Unregister<VideoMacro>();
            WikiPlex.Macros.Unregister<ContentLeftAlignmentMacro>();
            WikiPlex.Macros.Unregister<ContentRightAlignmentMacro>();
            WikiPlex.Macros.Register<AlertMacro>();
            WikiPlex.Macros.Register<IntroductionMacro>();
            WikiPlex.Macros.Register<MarkupMacro>();
            WikiPlex.Macros.Register<ParagraphMacro>();
            WikiPlex.Macros.Register<ProcedureMacro>();
            WikiPlex.Macros.Register<SectionMacro>();
            WikiPlex.Macros.Register<StepMacro>();
            WikiPlex.Macros.Register<TopicLinkMacro>();
            WikiPlex.Macros.Register<TopicMacro>();

            // renderers registration
            WikiPlex.Renderers.Unregister<IndentationRenderer>();
            WikiPlex.Renderers.Unregister<LinkRenderer>();
            WikiPlex.Renderers.Unregister<ListItemRenderer>();
            WikiPlex.Renderers.Unregister<SourceCodeRenderer>();
            WikiPlex.Renderers.Unregister<TableRenderer>();
            WikiPlex.Renderers.Unregister<TextFormattingRenderer>();
            WikiPlex.Renderers.Unregister<TopicRenderer>();
            WikiPlex.Renderers.Register<AlertRenderer>();
            WikiPlex.Renderers.Register<ContainerRenderer>();
            WikiPlex.Renderers.Register<Renderers.IndentationRenderer>();
            WikiPlex.Renderers.Register<Renderers.LinkRenderer>();
            WikiPlex.Renderers.Register<Renderers.ListItemRenderer>();
            WikiPlex.Renderers.Register<Renderers.SourceCodeRenderer>();
            WikiPlex.Renderers.Register<Renderers.TableRenderer>();
            WikiPlex.Renderers.Register<Renderers.TextFormattingRenderer>();
            WikiPlex.Renderers.Register<TopicLinkRenderer>();
            WikiPlex.Renderers.Register<TopicRenderer>();

            // scope augmenters
            ScopeAugmenters.Unregister<TableMacro>();
            ScopeAugmenters.Register<TableMacro, TableScopeAugmenter>();
        }

        /// <summary>
        /// Renders the wiki content using the statically registered macros and renderers.
        /// </summary>
        /// <param name="wikiContent">The wiki content to be rendered.</param>
        /// <returns>The rendered maml content.</returns>
        public string Render(string wikiContent)
        {
            if (string.IsNullOrEmpty(wikiContent))
                return wikiContent;

            wikiContent = wikiContent.Replace("\r\n", "\n");

            var parser = new MacroParser(compiler);
            var formatter = new MacroFormatter(WikiPlex.Renderers.All);

            parser.Parse(wikiContent, WikiPlex.Macros.All, ScopeAugmenters.All, formatter.RecordParse);

            return formatter.Format(wikiContent);
        }
    }
}